/*
    libnbds
    Non-blocking Data Structures Library

    Copyright (C) 2011 Paweł Dziepak

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef NBDS_THREAD_PRIVATE_H
#define NBDS_THREAD_PRIVATE_H

#include <pthread.h>

namespace nbds {
	class thread_private_base {
	private:
		void *(*creator)();

		pthread_key_t key;

	protected:
		thread_private_base(void*(*)(), void(*)(void*));
		~thread_private_base();

		void *get_ptr();

		bool exists_();
	};

	template<typename T>
	class thread_private : public thread_private_base {
	private:
		static void *creat() {
			return new T;
		}

		static void destr(void *ptr) {
			delete reinterpret_cast<T*>(ptr);
		}
	public:
		thread_private() : thread_private_base(creat, destr) { }

		bool exists() {
			return exists_();
		}

		T &operator*() {
			return *reinterpret_cast<T*>(get_ptr());
		}

		T *operator->() {
			return reinterpret_cast<T*>(get_ptr());
		}

		T *ptr() {
			return reinterpret_cast<T*>(get_ptr());
		}
	};
}

#endif
